package cn.pugle.base.TExp;

/**
 * 唉， 和liushen的前缀表达式+栈的相比，真是蠢的方法了，tzpdo
 * Created by tzp on 16-2-15.<br/>
 */
public class TParseUtil {
    public static final char And = '&';
    public static final char Or = '|';
    public static final char Not = '!';
    public static final char LeftParenthese = '(';
    public static final char RightParenthese = ')';

    /**
     * parse Tid表达式, 按照集合运算从左到右的运算顺序即 a|b&c ==> ((a|b)&c) <br/>
     * 不考虑null和0长度的输入 空白字符等错误输入
     */
    public TExp parse(String expStr) throws Exception {
        //从右向左读取下一组
        String nextGroup = null, remainStr = null;
        if (expStr.length() == 0) {
            return null;
        }
        if (expStr.charAt(expStr.length() - 1) == RightParenthese) {
            int leftPar = expStr.indexOf(LeftParenthese);
            nextGroup = expStr.substring(leftPar + 1, expStr.length() - 1);
            remainStr = expStr.substring(0, leftPar);
        } else {
            for (int i = expStr.length() - 1; i >= 0; i--) {
                if (expStr.charAt(i) == And || expStr.charAt(i) == Or || expStr.charAt(i) == Not) {
                    nextGroup = expStr.substring(i + 1, expStr.length());
                    remainStr = expStr.substring(0, i + 1);
                    break;
                }
                if (i == 0) {//循环的最后一次,即没有 与或非
                    return new TTagExp(expStr);
                }
            }
        }

        if (remainStr.length() != 0) {
            if (remainStr.charAt(remainStr.length() - 1) == And) {
                return new TAndExp(parse(remainStr.substring(0, remainStr.length() - 1)),
                        parse(nextGroup));
            } else if (remainStr.charAt(remainStr.length() - 1) == Or) {
                return new TOrExp(parse(remainStr.substring(0, remainStr.length() - 1)),
                        parse(nextGroup));
            } else if (remainStr.charAt(remainStr.length() - 1) == Not) {
                if (remainStr.length() == 1) {
                    return new TNotExp(parse(nextGroup));
                } else if (remainStr.charAt(remainStr.length() - 2) == And) {
                    return new TAndExp(parse(remainStr.substring(0, remainStr.length() - 2)),
                            new TNotExp(parse(nextGroup)));
                } else if (remainStr.charAt(remainStr.length() - 2) == Or) {
                    return new TOrExp(parse(remainStr.substring(0, remainStr.length() - 2)),
                            new TNotExp(parse(nextGroup)));
                } else {
                    throw new Exception("parse Tid expression error");
                }
            } else {
                throw new Exception("parse Tid expression error");
            }
        } else {
            return parse(nextGroup);
        }
    }

    public static void main(String[] args) throws Exception {
        char or = Or;
//        String s = "a&(c|b)&d";
        String s = "516&(!515)";
        TExp tExp = new TParseUtil().parse(s);
        System.out.println("parse \"" + s + "\" result : " + tExp);
        TLog tLog = new TLog();
        tLog.addTid("516");
        System.out.println(tExp.matches(tLog));
    }
}
